/// <summary>
// CodeFx.MySqlProviders - .NET Providers for MySql using the framework CodeFx
// Laurent Morisseau
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// Laurent Morisseau
/// </summary>
/// <author><a href="mailto:laurent.morisseau@gmail.com">Laurent Morisseau</a></author>

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls.WebParts;
using MySql.Data.MySqlClient;
using System.Collections.Specialized;
using System.Globalization;
using System.Configuration.Provider;

namespace CodeFx.MySqlProviders
{
    public class MySqlPersonalizationProvider : PersonalizationProvider
    {
        // Fields
        private string _AppName;
        private const int maxStringLength = 0x100;

        // Nested Types
        private enum ResetUserStateMode
        {
            PerInactiveDate,
            PerPaths,
            PerUsers
        }

        public override string ApplicationName
        {
            get { return _AppName; }
            set { _AppName = value; }
        }

        public MySqlPersonalizationProvider()
        {
        }

        private MySqlParameter CreateParameter(string paramName, MySqlDbType dbType, object objValue)
        {
            MySqlParameter parameter1 = new MySqlParameter(paramName, dbType);
            if (objValue == null)
            {
                objValue = string.Empty;
            }
            parameter1.Value = objValue;
            return parameter1;
        }

        private PersonalizationStateInfoCollection FindSharedState(string path, int pageIndex, int pageSize, out int totalRecords)
        {
            totalRecords = 0;
            object count = Aspnet_personalizationperuserDTO.CountSharedState(this.ApplicationId, path, (string)null, DateTime.MaxValue);
            if (count != null)
            {
                totalRecords = (int)count;
            }
            /// Attention ici en fait je fait comme FindState
            //return Aspnet_personalizationperuserDTO.FindSharedState(this.ApplicationName, path, DateTime.MaxValue, (string)null, pageSize * pageIndex, pageSize);
            return Aspnet_personalizationperuserDTO.FindSharedState(this.ApplicationId, path, DateTime.MaxValue, (string)null, pageSize * pageIndex, pageSize);
        }
        public override PersonalizationStateInfoCollection FindState(PersonalizationScope scope, PersonalizationStateQuery query, int pageIndex, int pageSize, out int totalRecords)
        {
            PersonalizationProviderHelper.CheckPersonalizationScope(scope);
            PersonalizationProviderHelper.CheckPageIndexAndSize(pageIndex, pageSize);
            if (scope == PersonalizationScope.Shared)
            {
                string text1 = null;
                if (query != null)
                {
                    text1 = StringHelper.CheckAndTrimString(query.PathToMatch, "query.PathToMatch", false, 0x100);
                }
                return this.FindSharedState(text1, pageIndex, pageSize, out totalRecords);
            }
            string text2 = null;
            DateTime time1 = DateTime.MaxValue ;
            string text3 = null;
            if (query != null)
            {
                text2 = StringHelper.CheckAndTrimString(query.PathToMatch, "query.PathToMatch", false, 0x100);
                time1 = query.UserInactiveSinceDate;
                text3 = StringHelper.CheckAndTrimString(query.UsernameToMatch, "query.UsernameToMatch", false, 0x100);
            }
            return this.FindUserState(text2, time1, text3, pageIndex, pageSize, out totalRecords);

        }

        private PersonalizationStateInfoCollection FindUserState(string path, DateTime inactiveSinceDate, string username, int pageIndex, int pageSize, out int totalRecords)
        {
            totalRecords = 0;
            object count = Aspnet_personalizationperuserDTO.CountSharedState(this.ApplicationId, path, username, inactiveSinceDate);
            if (count != null)
            {
                totalRecords = (int)count;
            }
            /// Attention ici en fait je fait comme FindState
            //return Aspnet_personalizationperuserDTO.FindSharedState(this.ApplicationName,  path, inactiveSinceDate, username, pageSize * pageIndex, pageSize);
            return Aspnet_personalizationperuserDTO.FindSharedState(this.ApplicationId, path, inactiveSinceDate, username, pageSize * pageIndex, pageSize);
        }

        private int GetCountOfSharedState(string path)
        {
            object count = Aspnet_personalizationperuserDTO.GetCountOfSharedState(true, this.ApplicationId, path, (string)null, DateTime.MaxValue);
            if (count != null)
            {
                return (int)count;
            }
            else
                return 0;
        }

        public override int GetCountOfState(PersonalizationScope scope, PersonalizationStateQuery query)
        {
            PersonalizationProviderHelper.CheckPersonalizationScope(scope);
            if (scope == PersonalizationScope.Shared)
            {
                string text1 = null;
                if (query != null)
                {
                    text1 = StringHelper.CheckAndTrimString(query.PathToMatch, "query.PathToMatch", false, 0x100);
                }
                return this.GetCountOfSharedState(text1);
            }
            string text2 = null;
            DateTime time1 = DateTime.MaxValue ;
            string text3 = null;
            if (query != null)
            {
                text2 = StringHelper.CheckAndTrimString(query.PathToMatch, "query.PathToMatch", false, 0x100);
                time1 = query.UserInactiveSinceDate;
                text3 = StringHelper.CheckAndTrimString(query.UsernameToMatch, "query.UsernameToMatch", false, 0x100);
            }
            return this.GetCountOfUserState(text2, time1, text3);
        }

        private int GetCountOfUserState(string path, DateTime inactiveSinceDate, string username)
        {
            object count = Aspnet_personalizationperuserDTO.GetCountOfSharedState(false, this.ApplicationId, path, username, inactiveSinceDate);
            if (count != null)
            {
                return (int)count;
            }
            else
                return 0; 
        }

        public override void Initialize(string name, NameValueCollection configSettings)
        {
            if (configSettings == null)
            {
                throw new ArgumentNullException("configSettings");
            }
            if (string.IsNullOrEmpty(name))
            {
                name = "MySqlPersonalizationProvider";
            }
            if (string.IsNullOrEmpty(configSettings["description"]))
            {
                configSettings.Remove("description");
                configSettings.Add("description", "SqlPersonalizationProvider_Description");
            }
            base.Initialize(name, configSettings);
            this._AppName = configSettings["applicationName"];
            if (this._AppName != null)
            {
                configSettings.Remove("applicationName");
                if (this._AppName.Length > 0x100)
                {
                    throw new ProviderException("PersonalizationProvider_ApplicationNameExceedMaxLength");
                }
            }
            
            string text1 = configSettings["connectionStringName"];
            if (string.IsNullOrEmpty(text1))
            {
                throw new ProviderException("PersonalizationProvider_NoConnection");
            }
            /// ConnectionString
            ConnectionString.Current.ConnectionStringName = configSettings["connectionStringName"];
            
            configSettings.Remove("connectionStringName");
            configSettings.Remove("commandTimeout");
            if (configSettings.Count > 0)
            {
                throw new ProviderException("PersonalizationProvider_UnknownProp");
            }
        }

        private byte[] LoadPersonalizationBlob(string path, string userName)
        {
            uint appid = ApplicationId;
            if (appid == 0)
                return new byte[0];
            uint pathid = Aspnet_pathsDTO.GetPathId(path, appid);
            if (pathid == 0)
                return new byte[0];

            if (userName != null)
            {
                uint userid = Aspnet_usersDTO.GetUserId(userName, appid);
                if (userid == 0)
                    return new byte[0];
                Aspnet_usersDTO.Update_LastActivityDateWithPersistance(userid, userName );
                return Aspnet_personalizationperuserDTO.SelectByFk_UserId_PathId(userid, pathid);
            }
            else
            {
                return Aspnet_personalizationallusersDTO.Select_PathId(pathid);
            }
        }
        protected override void LoadPersonalizationBlobs(WebPartManager webPartManager, string path, string userName, ref byte[] sharedDataBlob, ref byte[] userDataBlob)
        {
            sharedDataBlob = null;
            userDataBlob = null;
            try
            {
                sharedDataBlob = this.LoadPersonalizationBlob(path, null);
                if (!string.IsNullOrEmpty(userName))
                {
                    userDataBlob = this.LoadPersonalizationBlob(path, userName);
                }

            }
            catch
            {
                throw;
            }
        }

        private int ResetAllState(PersonalizationScope scope)
        {
            if (scope == PersonalizationScope.Shared)
                Aspnet_personalizationallusersDTO.Delete_AllState(this.ApplicationId);
            else
                Aspnet_personalizationperuserDTO.Delete_AllState(this.ApplicationId);
            return 0; 
        }

        protected override void ResetPersonalizationBlob(WebPartManager webPartManager, string path, string userName)
        {
            this.ResetPersonalizationState(path, userName); 
        }

        private void ResetPersonalizationState(string path, string userName)
        {
            uint appid = ApplicationId;
            if (appid == 0)
                return;
            uint pathid = Aspnet_pathsDTO.GetPathId(path, appid);
            if (pathid == 0)
                return;

            if (userName != null)
            {
                uint userid = Aspnet_usersDTO.GetUserId(userName, appid);
                if (userid == 0)
                    return;
                Aspnet_usersDTO.Update_LastActivityDateWithPersistance(userid,userName );
                Aspnet_personalizationperuserDTO.DeleteByFk_PathId_UserId (userid, pathid);
            }
            else
            {
                Aspnet_personalizationallusersDTO.DeleteByFk_PathId(pathid);
            }
        }

        public override int ResetState(PersonalizationScope scope, string[] paths, string[] usernames)
        {
            PersonalizationProviderHelper.CheckPersonalizationScope(scope);
            paths = PersonalizationProviderHelper.CheckAndTrimNonEmptyStringEntries(paths, "paths", false, false, 0x100);
            usernames = PersonalizationProviderHelper.CheckAndTrimNonEmptyStringEntries(usernames, "usernames", false, true, 0x100);
            if (scope == PersonalizationScope.Shared)
            {
                PersonalizationProviderHelper.CheckUsernamesInSharedScope(usernames);
                return this.ResetSharedState(paths);
            }
            PersonalizationProviderHelper.CheckOnlyOnePathWithUsers(paths, usernames);
            return this.ResetUserState(paths, usernames);
        }

        public override int ResetUserState(string path, DateTime userInactiveSinceDate)
        {
            path = StringHelper.CheckAndTrimString(path, "path", false, 0x100);
            string[] textArray1 = (path == null) ? null : new string[] { path };
            return this.ResetUserState(ResetUserStateMode.PerInactiveDate, userInactiveSinceDate, textArray1, null);
        }


        private int ResetUserState(string[] paths, string[] usernames)
        {
            bool flag1 = (paths != null) && (paths.Length != 0);
            bool flag2 = (usernames != null) && (usernames.Length != 0);
            if (!flag1 && !flag2)
            {
                return this.ResetAllState(PersonalizationScope.User);
            }
            if (!flag2)
            {
                return this.ResetUserState(ResetUserStateMode.PerPaths, DateTime.MaxValue, paths, usernames);
            }
            return this.ResetUserState(ResetUserStateMode.PerUsers, DateTime.MaxValue, paths, usernames);
        }


        private int ResetUserState(ResetUserStateMode mode, DateTime userInactiveSinceDate, string[] paths, string[] usernames)
        {
            string text1 = ((paths != null) && (paths.Length > 0)) ? paths[0] : null;
            if (mode == ResetUserStateMode.PerInactiveDate)
            {
                Aspnet_personalizationperuserDTO.DeleteUserState(ApplicationId , userInactiveSinceDate, (string)null, text1);
            }
            else if (mode == ResetUserStateMode.PerPaths)
            {
                foreach (string text2 in paths)
                {
                    Aspnet_personalizationperuserDTO.DeleteUserState(ApplicationId, DateTime.MaxValue, (string)null, text2);
                }
            }
            else
            {
                foreach (string text3 in usernames)
                {
                    Aspnet_personalizationperuserDTO.DeleteUserState(ApplicationId, DateTime.MaxValue, text3, text1);
                }
            }
            return 0;
        }

        protected override void SavePersonalizationBlob(WebPartManager webPartManager, string path, string userName, byte[] dataBlob)
        {
            this.SavePersonalizationState(path, userName, dataBlob);
        }

        private void SavePersonalizationState(string path, string userName, byte[] state)
        {

            uint appid = ApplicationId;
            if (appid == 0)
                return;
            uint pathid = Aspnet_pathsDTO.GetPathId(path, appid);
            if (pathid == 0)
            {
                Aspnet_pathsDAL paths = new Aspnet_pathsDAL ();
                paths.ApplicationId = appid;
                paths.Path = path;
                Aspnet_pathsDTO.Insert(paths);
                pathid = Aspnet_pathsDTO.GetLastId(paths);
            }

            if (userName != null)
            {
                uint userid = Aspnet_usersDTO.GetUserId(userName, appid);
                if (userid == 0)
                {
                    Aspnet_usersDAL user = new Aspnet_usersDAL ();
                    user.ApplicationId = appid;
                    user.LastActivityDate = DateTime.UtcNow;
                    user.UserName = userName;
                    user.IsAnonymous = 0;
                    Aspnet_usersDTO.Insert(user);
                    userid = Aspnet_usersDTO.GetLastId(user);
                }
                Aspnet_usersDTO.Update_LastActivityDateWithPersistance(userid,userName );
                Aspnet_personalizationperuserDAL peruser = new Aspnet_personalizationperuserDAL();
                peruser.PageSettings = state;
                peruser.UserId = userid;
                peruser.PathId = pathid;
                peruser.LastUpdatedDate = DateTime.UtcNow;
                if (Aspnet_personalizationperuserDTO.Exist_UserId_PathId(userid, pathid))
                    Aspnet_personalizationperuserDTO.Update_UserId_PathId(peruser);
                else
                    Aspnet_personalizationperuserDTO.Insert(peruser);
            }
            else
            {
                Aspnet_personalizationallusersDAL peruser = new Aspnet_personalizationallusersDAL();
                peruser.PageSettings = state;
                peruser.PathId = pathid;
                peruser.LastUpdatedDate = DateTime.UtcNow;
                if (Aspnet_personalizationallusersDTO.Exist(pathid))
                    Aspnet_personalizationallusersDTO.Update(peruser);
                else
                    Aspnet_personalizationallusersDTO.Insert(peruser);
            }

        }

        private uint ApplicationId
        {
            get
            {
                return Aspnet_applicationsDTO.GetApplicationId(_AppName);
            }
        }

        private int ResetSharedState(string[] paths)
        {
            if (paths == null)
            {
                return this.ResetAllState(PersonalizationScope.Shared);
            }
            foreach (string text1 in paths)
            {
                Aspnet_personalizationallusersDTO.Delete_ShareState(this.ApplicationId, text1);
            }
            return 0;
                
        }
    }
}
